package cate.game.role.bag.hero;

import cate.common.table.item.IBagItemTpl;
import cate.common.util.GameResult;
import cate.game.attr.PowerAttrPart;
import cate.game.client.msg.MergeMsgSender;
import cate.game.event.EventPublisher;
import cate.game.event.hero.HeroPowerChangeEvent;
import cate.game.play.support.PlayBuildContext;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.res.RewardShow;
import cate.game.role.Role;
import cate.game.role.bag.IBagContainer;
import cate.game.role.bag.item.BaseBagItem;
import com.fasterxml.jackson.annotation.JsonIgnore;
import cp.solution.pattern.ICopiable;
import easy.java.practice.errorcode.EcResult;

import java.util.Map;

/**
 * 穿戴在英雄身上的东西
 * @param <E> 到底是啥东西
 */
public interface OnHeroItem<E extends BaseBagItem> extends ICopiable<OnHeroItem<E>> , EventPublisher {

    /**
     * 获取背包
     * @return BagContainer
     */
    IBagContainer<E> getItemBag();

    @JsonIgnore
    Map<Byte, E> getPosItems();

    default E getPosItem(byte pos) {
        return getPosItems().get(pos);
    }

    default void clearPosItems(){
        getPosItems().clear();
    }

    default GameResult<Void> preCheckOn(PlayBuildContext ctx, byte pos, E e){
        return new GameResult<>();
    }

    default GameResult<Byte> on(PlayBuildContext ctx, Hero hero, byte pos, E e){
        return on(ctx, hero, pos, e, null);
    }

    default GameResult<Byte> on(PlayBuildContext ctx, Hero hero, byte pos, E e, MergeMsgSender sender){
        GameResult<Byte> r = new GameResult<>();
        if (e == null || e.num <= 0) {
            return r.fail("物品不存在");
        }
        GameResult<Void> checkR = preCheckOn(ctx, pos, e);
        if (!checkR.ok()){
            return r.fail(checkR);
        }
        //要再判断一次这个位置是否存在装备，不能直接走off
        if (getPosItem(pos) != null) {
            //脱下之前的
            GameResult<Byte> offRes = off(ctx, hero, pos, false, sender);
            if (!offRes.ok()) {
                return offRes;
            }
        }
        doRealOn(pos,e);
        r.data = pos;
        getItemBag().notReallyRemoveItemByUid(e.uid,1,sender);
        //英雄战力变更
        if (hero != null) {
            //主角战力变更
            hero.getRole().getBase().updatePower();
            publishEvent(ctx, new HeroPowerChangeEvent(hero.getRole(), hero));
        }
        return r;
    }

    default GameResult<Byte> off(PlayBuildContext ctx, Hero hero, byte pos, boolean updatePower){
        return off(ctx, hero, pos, updatePower, null);
    }

    default GameResult<Byte> off(PlayBuildContext ctx, Hero hero, byte pos, boolean updatePower, MergeMsgSender sender){
        GameResult<Byte> r = new GameResult<>();
        E e = getPosItem(pos);
        if(e == null){
            return r.fail("物品不存在");
        }
        //获得之前身上的
        EcResult<Void> addRes;
        IBagItemTpl row = e.getTpl(ctx);
        if(row == null || row.unique() || e.unique()){
            addRes = getItemBag().addItem(e,sender);
        }else{
            addRes = getItemBag().addItem(e.tid,1,sender);
        }
        if(!addRes.ok()){
            return r.fail(addRes.message);
        }
        doRealOff(pos,e);
        r.data = pos;
        if (hero != null && updatePower) {
            hero.getRole().getBase().updatePower();
            publishEvent(ctx, new HeroPowerChangeEvent(hero.getRole(), hero));
        }
        return r;
    }

    /**
     * 这个背包慢了会发邮件
     * @param role role
     * @param hero hero
     * @param pos pos
     * @param updatePower updatepower
     * @return r
     */
    default GameResult<Byte> off(Role role, Hero hero, byte pos, boolean updatePower){
        GameResult<Byte> r = new GameResult<>();
        E e = getPosItem(pos);
        if(e == null){
            return r.fail("物品不存在");
        }
        //获得之前身上的
        EcResult<Void> addRes;
        IBagItemTpl row = e.getTpl(role.getGame().fight.getPlayBuildContext());
        if(row == null || row.unique() || e.unique()){
            MixRes instanceReward = new MixRes(e);
            addRes = instanceReward.add(role, true, role.log.getOperation() , null);
        }else{
            MixRes reward = new MixRes().addItem(new MixResItem(e.type, e.tid, 1));
            addRes = reward.add(role, true, role.log.getOperation() ,null);
        }
        if(!addRes.ok()){
            return r.fail(addRes.message);
        }
        doRealOff(pos,e);
        r.data = pos;
        if (updatePower) {
            hero.getRole().getBase().updatePower();
            publishEvent(role.getGame(), new HeroPowerChangeEvent(hero.getRole(), hero));
        }
        return r;
    }

    default RewardShow offAll(Role role, Hero hero, boolean updatePower){
       return offAll(role, hero, null, updatePower);
    }

    default RewardShow offAll(Role role, Hero hero, MergeMsgSender sender, boolean updatePower){
        // 脱掉所有装备 返回脱掉了什么
        RewardShow show = new RewardShow();
        getPosItems().values().forEach(e -> {
            IBagItemTpl row = e.getTpl(role.getGame().fight.getPlayBuildContext());
            if(row == null || row.unique() || e.unique()){
                MixRes instanceReward = new MixRes(e);
                instanceReward.add(role, true, role.log.getOperation() ,sender);
            } else {
                MixRes reward = new MixRes().addItem(new MixResItem(e.type, e.tid, 1));
                reward.add(role, true, role.log.getOperation() ,sender);
            }
            show.addBagItem(role.getGame(), e);
        });
        clearPosItems();
        if(updatePower){
            role.getBase().updatePower();
            publishEvent(role.getGame(), new HeroPowerChangeEvent(role, hero));
        }
        return show;
    }

    /**
     * 真正的穿动作
     * @param pos 位置
     * @param e sth
     */
    void doRealOn(byte pos, E e);

    /**
     * 真正的脱动作
     * @param pos 位置
     * @param e sth
     */
    void doRealOff(byte pos, E e);

    PowerAttrPart getPowerAttrPart(PlayBuildContext ctx);
}
